﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Iris.Engine;
using ModEngine;

namespace Iris.SortProcess
{
    public class SortProcess : IModule
    {
        private class Duel {

            public ImageSort B { get; private set;}
            public ImageSort A{ get; private set;}

            public Duel(ImageSort a, ImageSort b) {
                A = a;
                B = b;
            }
        }

        private List<Duel> DuelsToDo = new List<Duel>();
        private List<ImageSort> Images = new List<ImageSort>();
        private int DuelCount = 0;

        #region IModule

        string IModule.getDescriptionModule()
        {
            return "Gestion du Tri des images par algorithme 'hadoc'";
        }

        string IModule.getNameModule()
        {
            return "SortProcess";
        }

        string IModule.getVersion()
        {
            return "1.0";
        }

        void IModule.Dispose()
        {
            
        }
        #endregion

        public SortProcess() {

            SortCore.singleton.BeginLoadDataSourceEvent += on_BeginLoadDataSourceEvent;
            SortCore.singleton.LoadDataSourceEvent += on_LoadDataSource;
            SortCore.singleton.BeginLoadDuelEvent += LancerDuel;
            SortCore.singleton.EndLoadDuelEvent += EnregistrerDuel;
            SortCore.singleton.EndLoadDuelNullEvent += EnregistrerDuelNull;
            SortCore.singleton.BlameImageEvent += on_BlameImage;
            SortCore.singleton.ActivateImageEvent += on_ActivateImage;
        }

        public void LancerDuel()
        {
            if (DuelsToDo.Count == 0)
            {
                SortCore.singleton.LoadDuelPlusDeDuel();
            }
            else
            {
                Random rand = new Random();
                int i = rand.Next(0, DuelsToDo.Count - 1);
                //int i = 0;
                Duel duel = DuelsToDo[i];
                DuelCount++;
                SortCore.singleton.LoadDuel(duel.A, duel.B, DuelCount * 100 / (DuelCount + DuelsToDo.Count));
            }
        }

        public void EnregistrerDuelNull(ImageSort a, ImageSort b)
        {
            a.Equivalent.Add(b);
            b.Equivalent.Add(a);
            deleteDuel(a, b);

            UpdateRating(Images);
            SortCore.singleton.ImagesUpdated(Images);
        }

        public void EnregistrerDuel(ImageSort gagnant, ImageSort perdant)
        {
            gagnant.Gagnant.Add(perdant);
            perdant.Perdant.Add(gagnant);
            deleteDuel(gagnant, perdant);
            
            UpdateRating(Images);
            SortCore.singleton.ImagesUpdated(Images);
        }


        private void on_BeginLoadDataSourceEvent(string ressource)
        {
            DuelsToDo.Clear();
            Images.Clear();
            DuelCount = 0;
        }

        private void AddDuel(ImageSort image)
        {
            image.IsBlamed = false;
            foreach (ImageSort img in Images) {
                bool HasNotMatchesAndNotBlamed = !img.IsBlamed &&
                    image.Gagnant.Count(a => a == img) == 0 &&
                    image.Perdant.Count(a => a == img) == 0 &&
                    image.Equivalent.Count(a => a == img) == 0;

                if (HasNotMatchesAndNotBlamed) DuelsToDo.Add(new Duel(img, image));
            }

            UpdateRating(Images);
        }

        private void on_ActivateImage(ImageSort image)
        {
            if (image.IsBlamed) {
                AddDuel(image);
                SortCore.singleton.ImagesUpdated(Images);
            }
        }

        private void on_BlameImage(ImageSort image) {
            if (!image.IsBlamed)
            {
                image.IsBlamed = true;
                image.Score = 0;
                image.Rating = 0;

                DuelsToDo.RemoveAll(a => a.A == image || a.B == image);

                UpdateRating(Images);

                SortCore.singleton.ImagesUpdated(Images);   
            }
        }

        private void on_LoadDataSource(ImageSort image)
        {
            AddDuel(image);
            Images.Add(image);
        }

        private void deleteDuel (ImageSort a, ImageSort b) {
            
            for (int i = 0; i < DuelsToDo.Count; i++) {
                if (
                    (DuelsToDo[i].A == a && DuelsToDo[i].B == b)
                    || (DuelsToDo[i].A == b && DuelsToDo[i].B == a)
                   ) {
                        DuelsToDo.RemoveAt(i);
                        break;
                }
            }
        }

        private void UpdateRating(List<ImageSort> ListImagesSort)
        {
            foreach (ImageSort image in ListImagesSort)
            {

                /*
                1-12   |  1 Star
                13-37  |  2 Stars
                38-62  |  3 Stars
                63-87  |  4 Stars
                88-99  |  5 Stars
                */

                int win = image.Gagnant.Count(a => !a.IsBlamed);
                int draw = image.Equivalent.Count(a => !a.IsBlamed);
                int loose = image.Perdant.Count(a => !a.IsBlamed);

                int min = (win + draw + loose);
                int max = min * 2;
                image.Score = win * 2 + draw;

                image.Rating = (image.Score) <= 0 || max == 0
                    ? 0
                    : (uint)(image.Score * 99 / max);
            }
        }

    }
}
